﻿#include "framework.h"
#include "Const.h"
#include "Man.h"

// 全局变量
extern BaseGameObject* gBaseGameObjects[GAME_BOARD_GRID_COUNT_V][GAME_BOARD_GRID_COUNT_H];

// 函数声明
static void Man_Delete(BaseGameObject*);
static void Man_Dancing(Man*);
static BaseGameObject* Man_Move(Man*, UINT, MoveResult*);
static void CALLBACK Man_OnTimer(HWND, UINT, UINT_PTR, DWORD);

/**
 * 创建小人。
 * @param back      背后对象
 * @param drawer    绘图者
 * @param gameBoard 游戏区域
 * @param type      类型
 * @param x, y      左上角坐标
 * @return 小人
 */
BaseGameObject* New_Man(BaseGameObject* back, HDC drawer, HWND gameBoard, GameObjectType type, int x, int y) {
    TCHAR imageFilePath[MAX_PATH] = { 0 };

    // 创建父类对象
    BaseGameObject* baseGameObject = New_Box(back, drawer, type, x, y);
    Box* box = (Box*)(baseGameObject->mChild);

    // 创建本类对象
    Man* man = (Man*)calloc(1, sizeof(Man));

    // 初始化父类数据
    box->mChild = man;

    // 初始化父类函数
    baseGameObject->deleteSelf = Man_Delete;

    // 初始化本类数据
    man->mParent = box;
    man->mGameBoard = gameBoard;

    _stprintf_s(imageFilePath, MAX_PATH, IMAGE_FILE_PATH, type * 10 + 2);
    man->mImageLeft1 = LoadImage(NULL, imageFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

    _stprintf_s(imageFilePath, MAX_PATH, IMAGE_FILE_PATH, type * 10 + 3);
    man->mImageLeft2 = LoadImage(NULL, imageFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

    _stprintf_s(imageFilePath, MAX_PATH, IMAGE_FILE_PATH, type * 10 + 4);
    man->mImageRight1 = LoadImage(NULL, imageFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

    _stprintf_s(imageFilePath, MAX_PATH, IMAGE_FILE_PATH, type * 10 + 5);
    man->mImageRight2 = LoadImage(NULL, imageFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

    _stprintf_s(imageFilePath, MAX_PATH, IMAGE_FILE_PATH, type * 10 + 6);
    man->mImageUp1 = LoadImage(NULL, imageFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

    _stprintf_s(imageFilePath, MAX_PATH, IMAGE_FILE_PATH, type * 10 + 7);
    man->mImageUp2 = LoadImage(NULL, imageFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

    man->mCurrentImage1 = baseGameObject->mImage;
    man->mCurrentImage2 = box->mImage2;

    // 初始化本类函数
    man->move = Man_Move;
    man->dancing = Man_Dancing;

    // 开始跳舞
    SetTimer(gameBoard, (UINT_PTR)man, TIMER_INIT, Man_OnTimer);

    return baseGameObject;
}

/**
 * 删除小人。
 * @param baseGameObject    基本游戏物体
 */
static void Man_Delete(BaseGameObject* baseGameObject) {
    Box* box = (Box*)baseGameObject->mChild;
    Man* man = (Man*)box->mChild;

    // 停止定时器
    KillTimer(man->mGameBoard, (UINT_PTR)man);

    // 删除本类
    DeleteObject(man->mImageLeft1);
    DeleteObject(man->mImageLeft2);
    DeleteObject(man->mImageRight1);
    DeleteObject(man->mImageRight2);
    DeleteObject(man->mImageUp1);
    DeleteObject(man->mImageUp2);
    free(man);

    // 删除父类
    Box_Delete(baseGameObject);
}

/**
 * 小人跳舞。
 * @param man   小人
 */
static void Man_Dancing(Man* man) {
    Box* box = man->mParent;
    BaseGameObject* baseGameObject = box->mParent;

    if (box->mCurrentImage == man->mCurrentImage1) {
        box->mCurrentImage = man->mCurrentImage2;
    } else {
        box->mCurrentImage = man->mCurrentImage1;
    }
    SelectObject(baseGameObject->mImageDC, box->mCurrentImage);
    BitBlt(baseGameObject->mDrawer, baseGameObject->mX * GRID_SIZE, baseGameObject->mY * GRID_SIZE,
        GRID_SIZE, GRID_SIZE, baseGameObject->mImageDC, 0, 0, SRCCOPY);
    InvalidateRect(man->mGameBoard, NULL, FALSE);
}

/**
 * 小人移动。
 * @param man           小人
 * @param direction     方向
 * @param moveResult    移动结果
 * @return 被推动的箱子
 */
static BaseGameObject* Man_Move(Man* man, UINT direction, MoveResult* moveResult) {
    Box* box = man->mParent;
    BaseGameObject* baseGameObject = box->mParent;
    BaseGameObject* movedBox = NULL;

    int destX = baseGameObject->mX, destY = baseGameObject->mY; // 新位置的坐标

    // 根据方向，计算新位置的坐标和图片
    switch (direction) {
        case VK_DOWN:
            destY++;
            man->mCurrentImage1 = baseGameObject->mImage;
            man->mCurrentImage2 = box->mImage2;
            break;
        case VK_LEFT:
            destX--;
            man->mCurrentImage1 = man->mImageLeft1;
            man->mCurrentImage2 = man->mImageLeft2;
            break;
        case VK_RIGHT:
            destX++;
            man->mCurrentImage1 = man->mImageRight1;
            man->mCurrentImage2 = man->mImageRight2;
            break;
        case VK_UP:
            destY--;
            man->mCurrentImage1 = man->mImageUp1;
            man->mCurrentImage2 = man->mImageUp2;
            break;
    }

    // 重新设置图片
    box->mCurrentImage = man->mCurrentImage1;

    // 先移动旁边的物体
    movedBox = gBaseGameObjects[destY][destX]->move(gBaseGameObjects[destY][destX], direction, moveResult);
    if (*moveResult == NO_MOVE) {
        return NULL;
    }

    // 移动小人
    Box_Move(baseGameObject, direction, moveResult);

    return movedBox;
}

/**
 * 定时器事件的响应函数。
 * @param window    窗口
 * @param msg       消息
 * @param timerId   定时器 id
 * @param time      时间
 */
void CALLBACK Man_OnTimer(HWND window, UINT msg, UINT_PTR timerId, DWORD time) {
    Man* man = (Man*)timerId;
    man->dancing(man);
    
    UNREFERENCED_PARAMETER(window);
    UNREFERENCED_PARAMETER(msg);
    UNREFERENCED_PARAMETER(time);
}
